import {
  createRouter,
  createWebHashHistory,
  type Router,
  type RouteRecordRaw,
} from "vue-router";
import {
  getFileName,
  ParallelTaskExecution,
  toLowerKebabCase,
} from "../utils";
import type { MenuItem, PageMetaData } from "../types";

// 默认的页面配置信息
const defaultPageConfig: PageMetaData = {
  name: "未知页面",
  hiddenInMenu: false,
  access: ["notshow"],
};

// 获取路径全称
const getFullPathName = (filePath: string) =>
  filePath.replace(/^\.*\/*(src)*\/pages\//, "");

const getCateName = (filePath: string) =>
  getFullPathName(filePath)
    .split("/")
    .map((v) => toLowerKebabCase(v))
    .join("/");

// 获取上一级目录
const getParentCateName = (filePath: string) => {
  if (!filePath) return "";
  const list = filePath.split("/");
  list.pop();
  return list.join("/");
};

interface PagePathInfo {
  key: string; // 数据的key，关联页面路由信息和配置信息
  path: string; // 页面路径
  name: string; // 名称
  cateName: string; // 所在目录
  parentCateName: string; // 上一级目录
  isIndex?: boolean; // 是否为根路由页面
  routeName: string; // 路由名称
  routeFullName: string; // 路由全称
}
interface PageInfoData extends PagePathInfo {
  config: PageMetaData;
}

// 解析页面路径信息，返回页面的名称以及上级路径名
const resolvePathInfo = (
  path: string,
  isConfig = false
): PagePathInfo | null => {
  const pageName = toLowerKebabCase(
    getFileName(path).slice(0, isConfig ? -10 : -4)
  );
  if (!pageName) {
    return null;
  }
  const cateName = getParentCateName(getCateName(path));
  const isIndex = pageName === "index";
  return {
    key: `${cateName}/${pageName}`,
    path: getFullPathName(path),
    name: isIndex ? cateName : `${cateName}/${pageName}`,
    cateName,
    parentCateName: getParentCateName(cateName),
    routeFullName: "/" + (isIndex ? cateName : `${cateName}/${pageName}`),
    routeName: isIndex ? "/" + getFileName(cateName) : `/${pageName}`,
    isIndex,
  };
};

// 解析页面配置信息
const resolvePageConfigs = async (): Promise<Map<string, PageInfoData>> => {
  // 获取页面配置
  const pageConfigs = import.meta.glob("../pages/**/*PageConfig.ts");

  // 获取页面配置信息
  const getPageConfig = async (
    configPath: string
  ): Promise<PageInfoData | null> => {
    if (!configPath) {
      return null;
    }
    try {
      const pathInfo = resolvePathInfo(configPath, true);
      if (!pathInfo) {
        return null;
      }
      if (pageConfigs[configPath]) {
        const config = await pageConfigs[configPath]();
        return {
          ...pathInfo,
          config: (config as any).default,
        };
      } else {
        return {
          ...pathInfo,
          config: { ...defaultPageConfig },
        };
      }
    } catch (err) {
      return null;
    }
  };

  return new Promise((resolve) => {
    const resultMap: Map<string, PageInfoData> = new Map();
    const totalCount = Object.keys(pageConfigs).length;
    const taskResolve = new ParallelTaskExecution(3);
    let resolveCount = 0;
    for (const configPath in pageConfigs) {
      taskResolve
        .addTask(() => getPageConfig(configPath))
        .then((pageInfo) => {
          if (pageInfo) {
            resultMap.set(pageInfo.key, pageInfo);
          }
        })
        .finally(() => {
          ++resolveCount;
          if (resolveCount >= totalCount) {
            resolve(resultMap);
          }
        });
    }
  });
};

// 构建树结构
const createTree = <
  T extends { meta?: Record<string, unknown>; children?: T[] }
>(
  list: T[],
  addWhenNoParent?: boolean,
  createParentItem?: (cur: T) => T
): T[] => {
  const map: Map<string, T> = new Map();
  for (const item of list) {
    if (!item.meta) {
      continue;
    }
    const { cateName, isIndex } = item.meta as unknown as PagePathInfo;
    if (isIndex) {
      map.set(cateName, item);
    }
  }

  const getParentItem = (parentKey: string, item: T) => {
    if (!parentKey) {
      return undefined;
    }
    const result = map.get(parentKey);
    if (!result) {
      if (createParentItem) {
        return createParentItem(item);
      }
      return getParentItem(getParentCateName(parentKey), item);
    }
    return result;
  };

  const resultList: T[] = [];
  for (const item of list) {
    if (!item.meta) {
      resultList.push(item);
      continue;
    }
    const { cateName, isIndex, parentCateName } =
      item.meta as unknown as PagePathInfo;
    const parentKey = isIndex ? parentCateName : cateName;
    if (!parentKey) {
      resultList.push(item);
      continue;
    }
    const parentItem = getParentItem(parentKey, item);
    if (!parentItem) {
      if (addWhenNoParent !== false) {
        resultList.push(item);
      }
      continue;
    }
    if (!parentItem.children) {
      parentItem.children = [];
    }
    parentItem.children.push(item);
    map.set(parentKey, parentItem);
  }
  return resultList;
};

export const createRouters = (
  cb: (route: Router, menus: MenuItem[]) => void
) => {
  resolvePageConfigs().then((pageConfigs) => {
    const pagePaths = import.meta.glob("../pages/**/*Page.vue");
    const list: RouteRecordRaw[] = [];
    const menuList: MenuItem[] = [];
    for (const path in pagePaths) {
      const pathInfo = resolvePathInfo(path);
      if (!pathInfo) {
        continue;
      }
      const pageInfoData = pageConfigs.get(pathInfo.key);
      const pageConfig = pageInfoData?.config || {
        name: pathInfo.name,
        hiddenInMenu: false,
        access: ["notshow"],
      };
      list.push({
        path: pathInfo.routeName,
        component: pagePaths[path],
        name: pathInfo.name,
        meta: {
          ...pathInfo,
          ...pageConfig,
        },
      });
      if (pathInfo.cateName.split('/')[0] === 'main') {
        menuList.push({
          key: pathInfo.key,
          name: pageConfig.name,
          meta: {
            ...pathInfo,
            ...pageConfig,
          },
        });
      }
    }

    // 构建路由树
    const routers = createTree(list, true, (val) => {
      const pathInfo = val.meta as unknown as PagePathInfo;
      const parentKey = pathInfo.isIndex
        ? pathInfo.parentCateName
        : pathInfo.cateName;
      const nameText = getFileName(parentKey);
      return {
        path: `/${nameText}`,
        component: import("../Empty.vue"),
        // name: nameText,
        redirect: val.path,
        children: [],
      };
    });
    // 构建菜单树
    const menus = createTree(menuList, false)[0]?.children || [];

    // 添加404和根路径路由
    routers.unshift({
      path: "/",
      redirect: "/main",
    });
    routers.push({
      path: "/:pathMatch(.*)*",
      name: "NotFound",
      component: () => import("../NotFound.vue"),
    });

    console.log("路由信息", routers);
    console.log("菜单信息", menus);

    cb(
      createRouter({
        history: createWebHashHistory(),
        routes: routers,
      }),
      menus
    );
  });
};
